package chen.web.user;

import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import chen.web.MyContextProvider;
import chen.web.event.method.MethodEvent;
import chen.web.event.method.MethodEventListener;

public abstract class SecurityListener extends MethodEventListener {

	protected EventConfigUtils utils = null;
	
	public static enum Status{
		success,	//通过验证
		fail, 		//验证失败
		half		//需要操作后再判断,用于需要返回结果的方法
	};
	
	private static Log log = LogFactory.getLog(SecurityListener.class);
	
	protected SecurityListener(EventConfigUtils utils){
		this.utils = utils;
	}
	
	
	public abstract Result authenticate(MethodEvent event);
	
	@Override
	protected void before(MethodEvent event) {
		// TODO Auto-generated method stub
		Role role = MyContextProvider.getMyContext().getAccount().getRole();
		//管理员角色不需要验证.
		if(InternalRoleProvider.getAdminRole().equals(role)){
			return;
		}

		Status status = null;
		Set<String> methodTypes= utils.getAllowMethdEventTypes(role);
		boolean access = methodTypes.contains(event.getType());

		String message = null;
		if(access){
			Result result = authenticate(event);
			status = result.getStatus();
			message = result.getMessage();
		} else {
			status = Status.fail;
		}
		
		if(status == Status.success){
			return;
		}else if(status == Status.fail){
			logFail(event, message);
			throw new NoPermissionException(message);
		} else if(status == Status.half){
			MyContextProvider.getMyContext().setAttribute("PermissionChecking_" + event.getType(), Boolean.TRUE);
			if(log.isDebugEnabled()){
				log.debug("需要事件发生后再验证. 事件:" + event.getType());
			}
		} else {
			throw new RuntimeException("未知错误");
		}
	}
	
	@Override
	protected void after(MethodEvent event) {
		// TODO Auto-generated method stub
		Boolean flag = (Boolean) MyContextProvider.getMyContext().getAttribute("PermisstionChecking_" + event.getType());
		if(flag == null || !flag){
			return;
		}
		Result result = authenticate(event);
		if(result.getStatus() == Status.success){
			return;
		} else if(result.getStatus() == Status.fail){
			logFail(event, result.getMessage());
			throw new NoPermissionException(event.getType());
		}else {
			throw new RuntimeException("权限检查中返回了无法理解的结果");
		}
	}
	
	private static void logFail(MethodEvent event, String message){
		if(log.isWarnEnabled()){
			StringBuffer info = new StringBuffer();
			Account acc = MyContextProvider.getMyContext().getAccount();
			info.append("没有权限执行事件:")
				.append(event.getType());
			if(message != null){
				info.append(",原因:")
					.append(message);
			}
			info.append(", 操作者id: ")
				.append(acc.getId())
				.append("用户名: ")
				.append(acc.getNickname())
				.append("角色: ")
				.append(acc.getRole().getName());
			log.info(info.toString());
		}
	}
	
	
	public static class Result{
		private Status status;
		private String message;
		public Result(Status status){
			this.status = status;
		}
		public Status getStatus(){
			return status;
		}
		public String getMessage(){
			return message;
		}
	}
	
}
